﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System.Security.Cryptography.X509Certificates;

using Elegant.Ui;

namespace iPdf
{
    class CertificateDropDown: TataDropDown
    {
        #region Fields
        private Elegant.Ui.PopupMenu Certificates;
        private CertificateDropDownItem defaultCertificate ;
        private string certificateStorePath = Helper.RoamingDir + "Certificates.xml";
        private string certificateTag = "Certificate";
        private string defaultAttr = "Default";
        private OpenFileDialog importCertificateDialog =
                Helper.CreateOpenFileDialog(FileFormat.PfxFormat, false);
        #endregion

        #region Properties

        private static TataRibbonPage HostPage
        {
            get
            {
                return Global.CurrentPage;
            }
        }

        public CertificateDropDownItem DefaultCertificate
        {
            get
            {
                if (defaultCertificate != null && !defaultCertificate.IsValid)
                {
                    defaultCertificate = null;
                    SelectedItem = string.Empty;
                    if (HostPage != null)
                    {
                        HostPage.UpdatePageOnlyControls();
                    }
                }
                return defaultCertificate;
            }
            set
            {
                if (!value.IsValid)
                {
                    return;
                }

                if (value != defaultCertificate)
                {
                    this.AddItem(value);
                    this.SelectedItem = value.Text;
                }

                defaultCertificate = value;
            }
        }

        public bool IsValid
        {
            get
            {
                return defaultCertificate != null && defaultCertificate.IsValid;
            }
        }

        public bool IsFile
        {
            get
            {
                if (defaultCertificate == null)
                {
                    return false;
                }

                return defaultCertificate.Source == CertificateSource.File;
            }
        }

        #endregion

        public CertificateDropDown()
        {
            InitializeComponents();
            this.Name = "Certificate";
            this.LoadDefaultMenuItem();
            this.defaultMenuItem.Text = "Import Your Digital Certificate";
            this.defaultMenuItem.Click += new EventHandler(ImportCertificate_Click);

            //load certificates into the drop down menu
            LoadSystemCertificates();
            LoadCertificates();
        }

        private void ImportCertificate_Click(object sender, EventArgs e)
        {
            if (importCertificateDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                DefaultCertificate = new CertificateDropDownItem(this, 
                    importCertificateDialog.FileName, CertificateItem_Click);
                HostPage.UpdatePageOnlyControls();
                Global.MainWindow.UpdateActionGroup();
            }
        }

        public void CertificateItem_Click(object sender, EventArgs e)
        {
            Elegant.Ui.ToggleButton menuItem = (Elegant.Ui.ToggleButton)sender;
            CertificateDropDownItem certItem = (CertificateDropDownItem)menuItem.Tag;


            if (!certItem.IsValid)
            {
                if (certItem == DefaultCertificate)
                {
                    this.RefreshMenuItems();
                }

                Global.MainWindow.UpdateActionGroup();
                HostPage.UpdatePageOnlyControls();
                Global.ShowNotification("The certificate " + Helper.QuoteString(certItem.Text) +
                                                " doesn't exist any more and thus it's been removed.");

                return;
            }

            DefaultCertificate = certItem;
            
            Global.MainWindow.UpdateActionGroup();
            HostPage.UpdatePageOnlyControls();
        }

        public override string[] ToStringArray()
        {
            List<string> strList = new List<string>();
            foreach (TataDropDownItem item in attachItems)
            {
                CertificateDropDownItem certItem = (CertificateDropDownItem)item;
                if (certItem.IsValid && certItem.Source == CertificateSource.File)
                {
                    strList.Add(item.Text);
                }
            }

            return strList.ToArray();
        }

        private void InitializeComponents()
        {
            Certificates = new Elegant.Ui.PopupMenu();

            ((System.ComponentModel.ISupportInitialize)(Certificates)).BeginInit();

            this.Id = "a184c9d1-dd8d-484b-88cb-df57f22c1a09";
            this.InformativenessMaximumLevel = "Elegant.Ui.RibbonGroupButtonInformativenessLevel:SmallImageWithText";
            this.InformativenessMinimumLevel = "Elegant.Ui.RibbonGroupButtonInformativenessLevel:SmallImageWithText";
            this.Location = new System.Drawing.Point(218, 50);
            this.MaxItemsCount = 10;
            this.Name = "this";
            this.Popup = Certificates;
            this.Size = new System.Drawing.Size(211, 24);
            this.SmallImages.Images.AddRange(new Elegant.Ui.ControlImage[] {
            new Elegant.Ui.ControlImage("Normal", global::iPdf.Properties.Resources.Certificate16)});
            this.TabIndex = 5;
            this.Text = "Import/Choose Digital Certificate";
            this.ButtonClick += new EventHandler(ImportCertificate_Click);
            // 
            // Certificates
            // 
            Certificates.PlacementMode = Elegant.Ui.PopupPlacementMode.Bottom;
            Certificates.Size = new System.Drawing.Size(100, 100);

            ((System.ComponentModel.ISupportInitialize)(Certificates)).EndInit();
        }

        protected void LoadSystemCertificates()
        {
            X509CertificateCollection sysCerts = SystemCertificateStore.SystemCertificates;
            foreach (X509Certificate cert in sysCerts)
            {
                CertificateDropDownItem item = new CertificateDropDownItem(this,
                                                        cert.Subject, CertificateItem_Click, CertificateSource.System);
                this.AddItem(item);
            }
        }

        protected void LoadCertificates()
        {
            List<string> certificates = new List<string>();

            if (File.Exists(certificateStorePath))
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(certificateStorePath);

                XmlNodeList nodeList = xmlDoc.GetElementsByTagName(certificateTag);

                foreach (XmlElement node in nodeList)
                {
                    string cert = node.InnerText;
                    if (!string.IsNullOrEmpty(cert) &&
                        !this.Contains(cert) &&
                        File.Exists(cert))
                    {
                        certificates.Add(cert);
                    }

                    if (node.GetAttribute(defaultAttr) == "true")
                    {
                        DefaultCertificate = new CertificateDropDownItem(this, cert, CertificateItem_Click);
                    }
                }
            }

            foreach (string cert in certificates)
            {
                CertificateDropDownItem item = 
                    new CertificateDropDownItem(this, cert, CertificateItem_Click);
                this.AddItem(item);
            }
        }

        public override void RefreshMenuItems()
        {
            base.RefreshMenuItems();
            if (HostPage != null)
            {
                HostPage.UpdatePageOnlyControls();
            }
            if (DropDownMenuItems.Count == 0 || attachItems.Count == 0)
            {
                defaultCertificate = null;
            }
        }

        public void StoreCertificates()
        {
            XmlDocument xmlDoc = Helper.CreateXmlDocument();
            XmlElement root = xmlDoc.CreateElement("Tata");
            xmlDoc.AppendChild(root);
            XmlElement certificatesNode = xmlDoc.CreateElement("Certificates");
            root.AppendChild(certificatesNode);
            string[] certificates = this.ToStringArray();
            foreach (string cert in certificates)
            {
                XmlElement xmlEle = xmlDoc.CreateElement(certificateTag);
                xmlEle.InnerText = cert;
                if (cert == defaultCertificate.Text)
                {
                    xmlEle.SetAttribute(defaultAttr, "true");
                }

                certificatesNode.AppendChild(xmlEle);
            }

            xmlDoc.Save(certificateStorePath);
        }
    }
}
